﻿using IMServer.Models;
using MongoDB.Driver;
using IMServer.Database;
using IMServer.Models.Message;

namespace IMServer.Services;

public class PendingRequestBoxesDbService
{
    private static readonly PendingRequestBoxesDbService _instance = new ();
    private static IMongoCollection<PendingRequestBox>? _pendingRequsetBoxesCollection;

    // 私有构造函数
    private PendingRequestBoxesDbService()
    {
        try
        {
            Console.WriteLine("Starting _pendingRequsetBoxesCollection initialization...");
            var dbContext = MongoDBContext.Instance;
            _pendingRequsetBoxesCollection = dbContext.PendingRequestBoxes;

            if (_pendingRequsetBoxesCollection == null)
                throw new InvalidOperationException("Failed to initialize PendingRequsetBoxes collection");

            // 创建索引
            var indexOptions = new CreateIndexOptions { Unique = true };
            var indexKeys = Builders<PendingRequestBox>.IndexKeys.Ascending(static x => x.UserId);
            _ = _pendingRequsetBoxesCollection.Indexes.CreateOne(
                new CreateIndexModel<PendingRequestBox>(indexKeys, indexOptions));

            Console.WriteLine("PendingRequestBoxesDbService initialized successfully");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error initializing PendingRequestBoxesDbService: {ex.Message}");
            throw;
        }
    }

    public static PendingRequestBoxesDbService Instance => _instance;
    
    public async Task<bool> CreatePendingRequestBoxAsync(string userId)
    {
        if (_pendingRequsetBoxesCollection == null)
            throw new InvalidOperationException("Database not initialized");

        try
        {
            var pendingRequestBox = new PendingRequestBox
            {
                UserId = userId,
                Messages = new List<SystemMessage>(),
                PendingCount = 0
            };

            await _pendingRequsetBoxesCollection.InsertOneAsync(pendingRequestBox);
            return true;
        }
        catch (MongoWriteException ex) when (ex.WriteError.Category == ServerErrorCategory.DuplicateKey)
        {
            // 如果消息箱已存在，返回 true
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
    
    // 插入消息
    public async Task<bool> InsertPendingRequestAsync(string userId, SystemMessage message)
    {
        if (_pendingRequsetBoxesCollection == null)
            throw new InvalidOperationException("Database not initialized");

        if (message is ReqSystemMessage)
        {
            ReqSystemMessage reqMessage = (ReqSystemMessage)message;
            // 如果是请求消息，则插入到消息列表中
            var update = Builders<PendingRequestBox>.Update
                .AddToSet(x => x.Messages, reqMessage)
                .Inc(x => x.PendingCount, 1);

            var options = new UpdateOptions { IsUpsert = true };

            var result = await _pendingRequsetBoxesCollection.UpdateOneAsync(
                x => x.UserId == userId,
                update,
                options);
            
            return result.ModifiedCount > 0 || result.UpsertedId != null;
        }
        else if(message is ResSystemMessage)
        {
            ResSystemMessage resMessage = (ResSystemMessage)message;
            // 如果是响应消息，则根据 messageId 删除消息
            var update = Builders<PendingRequestBox>.Update
                .PullFilter(x => x.Messages, m => m.MessageId == resMessage.RequestMessageId)
                .Inc(x => x.PendingCount, -1);
            
            var result = await _pendingRequsetBoxesCollection.UpdateOneAsync(
                x => x.UserId == userId
                , update);
            
            return result.ModifiedCount > 0 || result.UpsertedId != null;
        }
        else
        {
            // 其他类型的消息，抛出错误
            throw new ArgumentException("Invalid message type");
        }
    }
    
    // 拉取所有待处理消息
    public async Task<List<SystemMessage>> GetAllPendingRequestsAsync(string userId)
    {
        if (_pendingRequsetBoxesCollection == null)
            throw new InvalidOperationException("Database not initialized");
        
        var filter = Builders<PendingRequestBox>.Filter.Eq(x => x.UserId, userId);
        var result = await _pendingRequsetBoxesCollection.Find(filter).FirstOrDefaultAsync();
        return result?.Messages ?? new List<SystemMessage>();
    }
}